package com.mezz.bones.framework.crypto.resolve;

import cn.hutool.core.util.StrUtil;
import com.mezz.bones.framework.crypto.util.JasyptEncryptionUtil;
import com.ulisesbocchio.jasyptspringboot.EncryptablePropertyResolver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;

/**
 * 自定义配置属性解密器
 * 
 * @Author: zhuang
 * @Date: 2024/17/6 15:54
 * @Description: yml隐私数据加解密解析对象，加密数据使用 ENC(密文) 包裹
 * @Version: 1.0
 **/
@Configuration
@Slf4j
public class MyEncryptablePropertyResolver implements EncryptablePropertyResolver {

    private static final String ENCRYPTED_PREFIX = "ENC(";
    private static final String ENCRYPTED_SUFFIX = ")";

    private static String PASSWORD = null;

    static {
        // PASSWORD Java 系统属性 环境变量（例如，使用 -Djasypt.encryptor.password=8081 传递的参数）
        String password = System.getProperty("jasypt.encryptor.password");
        if (StrUtil.isBlank(password)) {
            // 默认使用test，生产环境在启动命令上指定参数
            PASSWORD = "test";
        } else {
            if (StrUtil.isBlank(password)) {
                log.error("jasypt.encryptor.password 未配置");
                throw new RuntimeException("jasypt.encryptor.password 未配置");
            }
            PASSWORD = password;
        }
    }

    @Override
    public String resolvePropertyValue(String value) {
        if (StrUtil.isBlank(value)) {
            return value;
        }
        // 以ENC(开头的,需要解密
        if (StrUtil.isNotBlank(value) && value.startsWith(ENCRYPTED_PREFIX) && value.endsWith(ENCRYPTED_SUFFIX)) {
            value = value.trim().substring(4, value.trim().length() - 1);
            value = decrypt(value);
        }
        // 不需要解密的值直接返回
        return value;
    }

    /**
     * 解密
     * 
     * @param value 待解密的值
     * @return 解密后的值
     */
    private String decrypt(String value) {
        try {
            return JasyptEncryptionUtil.decrypt(value, PASSWORD);
        } catch (Exception e) {
            log.error("yml 解密失败", e);
            throw e;
        }
    }

    /**
     * 加密
     * 
     * @param value 待加密的值
     * @return 加密后的值
     */
    public String encrypt(String value) {
        try {
            return JasyptEncryptionUtil.encrypt(value, PASSWORD);
        } catch (Exception e) {
            log.error("yml 加密失败", e);
            throw e;
        }
    }
}